package com.myzl.stream.util.hc;

import cn.hutool.core.date.DatePattern;
import com.sun.jna.Native;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.ObjectUtils;

import java.io.File;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

/**
 * @author Administrator
 * @date 2022年11月8日15:49:05
 */
@Slf4j
public class HCSDKUtil {

    /**
     * 动态库加载
     *
     * @return
     */
    public static HCNetSDK createSDKInstance(String path ,HCNetSDK hCNetSDK) {
        if (hCNetSDK == null) {
            synchronized (HCNetSDK.class) {
                String strDllPath = "";
                try {
                    if (isWindows()){
                        //win系统加载库路径
                        strDllPath = path+ "HCNetSDK.dll";
                    } else if (isLinux()){
                        //Linux系统加载库路径
                        strDllPath = path+ "libhcnetsdk.so";
                    }
                    File file = new File(strDllPath);
                    if (!file.exists()){
                        log.info("获取sdk失败，请检查sdk路径");
                        return null;
                    }
                    hCNetSDK = Native.load(strDllPath, HCNetSDK.class);
                } catch (Exception ex) {
                    log.error("loadLibrary: " + strDllPath + " Error: ",ex);
                    return null;
                }
            }
        }
        return hCNetSDK;
    }

    public static boolean loadSdk(String path,HCNetSDK hCNetSDK){
        if (isLinux() && hCNetSDK != null) {
            HCNetSDK.BYTE_ARRAY ptrByteArray1 = new HCNetSDK.BYTE_ARRAY(256);
            HCNetSDK.BYTE_ARRAY ptrByteArray2 = new HCNetSDK.BYTE_ARRAY(256);
            //这里是库的绝对路径，请根据实际情况修改，注意改路径必须有访问权限
            String strPath1 = path + "libcrypto.so.1.1";
            String strPath2 = path + "libssl.so.1.1";

            System.arraycopy(strPath1.getBytes(), 0, ptrByteArray1.byValue, 0, strPath1.length());
            ptrByteArray1.write();
            hCNetSDK.NET_DVR_SetSDKInitCfg(3, ptrByteArray1.getPointer());

            System.arraycopy(strPath2.getBytes(), 0, ptrByteArray2.byValue, 0, strPath2.length());
            ptrByteArray2.write();
            hCNetSDK.NET_DVR_SetSDKInitCfg(4, ptrByteArray2.getPointer());

            HCNetSDK.NET_DVR_LOCAL_SDK_PATH struComPath = new HCNetSDK.NET_DVR_LOCAL_SDK_PATH();
            System.arraycopy(path.getBytes(), 0, struComPath.sPath, 0, path.length());
            struComPath.write();
            hCNetSDK.NET_DVR_SetSDKInitCfg(2, struComPath.getPointer());
        }
        return true;
    }

    public static boolean initHCCamera(HCNetSDK hCNetSDK) {
        if (hCNetSDK != null){
            // 初始化
            boolean initSuc = hCNetSDK.NET_DVR_Init();
            if (!initSuc) {
                log.info("初始化失败");
                return false;
            }
        }
        return true;
    }
    public static int login(HCNetSDK hCNetSDK, String ip,short port, String username, String password){
        // 打印SDK日志
        hCNetSDK.NET_DVR_SetLogToFile(3, ".\\SDKLog\\", false);

        // 用户登陆操作
        /* 注册 */
        // 设备登录信息
        HCNetSDK.NET_DVR_USER_LOGIN_INFO m_strLoginInfo = new HCNetSDK.NET_DVR_USER_LOGIN_INFO();
        // 设备信息
        HCNetSDK.NET_DVR_DEVICEINFO_V40 m_strDeviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V40();
        m_strLoginInfo.sDeviceAddress = new byte[HCNetSDK.NET_DVR_DEV_ADDRESS_MAX_LEN];
        System.arraycopy(ip.getBytes(), 0, m_strLoginInfo.sDeviceAddress, 0, ip.length());
        m_strLoginInfo.wPort = port ;
        m_strLoginInfo.sUserName = new byte[HCNetSDK.NET_DVR_LOGIN_USERNAME_MAX_LEN];
        System.arraycopy(username.getBytes(), 0, m_strLoginInfo.sUserName, 0, username.length());
        m_strLoginInfo.sPassword = new byte[HCNetSDK.NET_DVR_LOGIN_PASSWD_MAX_LEN];
        System.arraycopy(password.getBytes(), 0, m_strLoginInfo.sPassword, 0, password.length());
        // 是否异步登录：false- 否，true- 是
        m_strLoginInfo.bUseAsynLogin = false;
        // write()调用后数据才写入到内存中
        m_strLoginInfo.write();

        int lUserID = hCNetSDK.NET_DVR_Login_V40(m_strLoginInfo, m_strDeviceInfo);
        if (lUserID == -1) {
            log.info("登录失败，错误码为" + hCNetSDK.NET_DVR_GetLastError());
        } else {
            log.info("登录成功！");

            // read()后，结构体中才有对应的数据
            m_strDeviceInfo.read();
        }
        return  lUserID;
    }

    public static boolean getWorkState(HCNetSDK hCNetSDK, int lUserID){
        //实现SDK中其余功能模快
        //判断是否获取到设备能力
        HCNetSDK.NET_DVR_WORKSTATE_V30 devWork = new HCNetSDK.NET_DVR_WORKSTATE_V30();
        if(!hCNetSDK.NET_DVR_GetDVRWorkState_V30(lUserID, devWork)){
            log.info("获取设备能力集失败,返回设备状态失败...............");
            return false;
        }
        return true;
    }

    public static boolean getPicture(HCNetSDK hCNetSDK, int lUserID,int channel,String fileNamePath){
        //抓图                     NET_DVR_PlayBackCaptureFile
        HCNetSDK.NET_DVR_JPEGPARA jpegInfo=new HCNetSDK.NET_DVR_JPEGPARA();
        //图片质量系数：0-最好，1-较好，2-一般
        jpegInfo.wPicQuality=2;
        //图片尺寸
        jpegInfo.wPicSize=2;
        boolean bFlag = hCNetSDK.NET_DVR_CaptureJPEGPicture(lUserID,channel,jpegInfo,fileNamePath);

        if (bFlag) {
            log.info("抓取图片成功,路径：" + fileNamePath);
            return true;
        } else {
            System.out.println("抓取图片失败："+hCNetSDK.NET_DVR_GetLastError());
            return false;
        }

    }

    public static boolean loginOut(HCNetSDK hCNetSDK, int lUserID){
        //用户注销
        if (lUserID>=0) {
            if (!hCNetSDK.NET_DVR_Logout(lUserID)) {
                log.info("注销失败，错误码为" + hCNetSDK.NET_DVR_GetLastError());
            } else {
                log.info("注销成功");
            }
            return true;
        } else {
            log.info("设备未登录");
            return true;
        }
    }

    public static boolean cleaSdk(HCNetSDK hCNetSDK){
        //释放SDK
        if (!hCNetSDK.NET_DVR_Cleanup()) {
            log.info("释放SDK，错误码为{}" , hCNetSDK.NET_DVR_GetLastError());
        } else {
            log.info("释放SDK成功");
        }
        return true;
    }

    public static String getFileName(String path,Integer deviceId){
        String currentDate = DateTimeFormatter.ofPattern(DatePattern.PURE_DATE_PATTERN).format(LocalDate.now());
        String currentDateTime = DateTimeFormatter.ofPattern(DatePattern.PURE_DATETIME_MS_PATTERN).format(LocalDateTime.now());
        //按照每天设置一个目录
        String filePath =  path + currentDate ;
        File files = new File(filePath);
        if(!files.exists()){
            files.mkdirs();
        }
        String deviceInfo = "";
        //设备信息
        if (!ObjectUtils.isEmpty(deviceId)){
            deviceInfo = deviceId +"_";
        }

        //按照日期文件夹放入图片
        return filePath + System.getProperty("file.separator")+ deviceInfo + currentDateTime+ ".jpg";
    }

    public static String getAiFileName(String path,Integer deviceId){
        String currentDate = DateTimeFormatter.ofPattern(DatePattern.PURE_DATE_PATTERN).format(LocalDate.now());
        String currentDateTime = DateTimeFormatter.ofPattern(DatePattern.PURE_DATETIME_MS_PATTERN).format(LocalDateTime.now());
        //按照每天设置一个目录
        String filePath =  path + currentDate ;
        File files = new File(filePath);
        if(!files.exists()){
            files.mkdirs();
        }
        String deviceInfo = "";
        //设备信息
        if (!ObjectUtils.isEmpty(deviceId)){
            deviceInfo = "_" + deviceId;
        }

        //按照日期文件夹放入图片
        return filePath + System.getProperty("file.separator") + currentDateTime + deviceInfo + ".jpg";
    }

    public static boolean isLinux() {
        return System.getProperty("os.name").toLowerCase().contains("linux");
    }

    public static boolean isWindows() {
        return System.getProperty("os.name").toLowerCase().contains("windows");
    }
}
